import { _decorator, Node, Material, Sprite } from 'cc';
import { ReactiveProperty } from '../../scripts/libs/rxjs/cc3/ReactiveProperty';
import { ResType, rm } from '../../scripts/managers/ResourceManager';
import { Observable, of } from 'rxjs';
import { TweenToStart } from '../../scripts/libs/rxjs/cc3/TweenStart';
import { TransparentPass } from '../../scripts/libs/rxjs/cc3/CommonObservable';
import { instantiate } from 'cc';
import { lm } from './LobbyManager';
import { StageInfo } from './game/basic';
import { SmartNodePool } from '../../scripts/libs/utils/SmartNodePool';
import { CaidaiHelper } from './CaidaiHelper';
import { DevConfig } from '../../scripts/managers/DevConfig';
import { stageNumMapTo } from '../../scripts/libs/utils/RandomChooseTools';
import { log } from 'cc';
import { ColorIdFromStage } from './ColorIdFromStage';
const { ccclass, property } = _decorator;

export class ResourceHelper {

    // Material
    static CommonMaterialReady = ReactiveProperty.Create(false);

    static HighlightSingleMaterialPath = 'ab_lobby/Materials/builtin-sprite-highlight-single';
    static get HighlightSingleMaterial(): Material {
        return rm.materials[this.HighlightSingleMaterialPath];
    }

    static CreateHighlightSingleFlush(node: Node) {
        let sprite = node.getComponent(Sprite);
        if (sprite == null) return of(null);
        return new Observable(observer => {
            sprite.customMaterial = this.HighlightSingleMaterial;
            let com = node.getComponent('effect_highlight_light_single');
            if (com == null) com = node.addComponent('effect_highlight_light_single');
            // com.useMaterialInstance = true;
            com['diff'] = -1;
            // com.rot = -.1;
            // com.transition = -.05;
            // com.width = .15;
            // com.color = color().fromHEX('FFFFFF80');
            let _sub = TweenToStart(com, .4, { diff: 1 }, { easing: 'sineOutIn' }).subscribe(TransparentPass(observer));
            return () => {
                if (_sub) _sub.unsubscribe();
                sprite.customMaterial = null;
                com?.destroy();
            }
        });
    }

    static GetStageJsonPath(stageId: number) {
        return `ab_lobby/Json/stage${stageId.toString().padStart(3, '0')}`;
    }

    static LoadStageAssets(stageId: number): Observable<StageInfo> {
        return new Observable(observer => {
            let rawStageId = stageId; // rawStageId用于控制关卡号在STAGE_NUM_MAX之内
            if (DevConfig.STAGE_RANDOM_REPEAT) {
                if (rawStageId > DevConfig.STAGE_NUM_MAX) {
                    // TODO: 映射到之前的关卡
                    // let stageIdz = (rawStageId - 1) % DevConfig.STAGE_NUM_MAX;
                    // let seed = Math.floor(rawStageId / DevConfig.STAGE_NUM_MAX).toString();
                    // let mapping = generateMapping(DevConfig.STAGE_NUM_MAX, seed + 1);
                    // rawStageId = mapping[stageIdz] + 1;
                    // log("stageNum over, repeat:", stageId, rawStageId);
                    rawStageId = stageNumMapTo(stageId).result;
                    log("stageNum over, repeat:", stageId, rawStageId);
                }
            }
            let path = this.GetStageJsonPath(rawStageId);
            if (rm.jsonAssets[path] != null) {
                observer.nextAndComplete(rm.jsonAssets[path].json as StageInfo);
            } else {
                rm.loadRes([
                    [path, ResType.JsonAsset]
                ]).subscribe({
                    next: _ => {
                        if (_.status != 0) {
                            lm.frontTipShow(`Load stage failed! (stage:${stageId}) rawStageId:${rawStageId}`);
                            observer.nextAndComplete(null);
                        }
                    },
                    complete: () => {
                        if (rm.jsonAssets[path] != null) {
                            let stageInfo = rm.jsonAssets[path].json as StageInfo;
                            if (stageInfo.stageId != null && stageInfo.stageId != stageId) {
                                console.warn('StageId in json is not match with stageId in file name.');
                                // return;
                            }
                            stageInfo.stageId = stageId;
                            observer.nextAndComplete(stageInfo);
                        }
                    }
                });
            }
        });
    }

    static Atlas_Tptex2_Path = 'ab_lobby/texture-2/tptex2';
    static GetTpTex2Atlas() {
        return rm.spriteAtlas[this.Atlas_Tptex2_Path];
    }

    static Atlas_joint_Path = 'ab_lobby/texture-1/joint';
    static GetJointAtlas() {
        return rm.spriteAtlas[this.Atlas_joint_Path];
    }

    static GetAtlasB0CXPath(cx: number) {
        return `ab_lobby/texture-1/b0c${cx}`;
    }

    static GetB0SpriteFrame(shapeId: number, colorId: number) {
        console.log('@GetB0SpriteFrame', shapeId, colorId);
        if (shapeId > 0 && colorId > 0) {
            return rm.spriteAtlas[this.GetAtlasB0CXPath(colorId)].getSpriteFrame(`c${colorId}/b0s${shapeId}c${colorId}`);
        }
    }

    static PrefabPath_ChangeSmoke = 'ab_lobby/Particle/Smoke0/ChangeSmoke/ChangeSmoke';
    // static PrefabPath_FlyItem = 'ab_lobby/Prefabs/Common/FlyItem';
    static PrefabPath_FlyCoin = 'ab_lobby/Prefabs/Common/FlyCoin';
    static PrefabPath_TutorialHand = 'ab_lobby/spine/TutorialHand/TutorialHand';
    // static PrefabPath_TutorialTip = 'ab_lobby/Prefabs/GamePanel/game/TutorialTip';
    static PrefabPath_BlinkPlateDestroy = 'ab_lobby/Particle/Blink0/BlinkPlateDestroy';
    static PrefabPath_BurstView = 'ab_lobby/Particle/Burst0/Burst0';
    static PrefabPath_Burst1View = 'ab_lobby/Particle/Burst0/Burst1';
    static PrefabPath_Burst2View = 'ab_lobby/Particle/Burst0/Burst2';
    static PrefabPath_Burst3View = 'ab_lobby/Particle/Burst0/Burst3';
    static PrefabPath_Burst4View = 'ab_lobby/Particle/Burst0/Burst4';
    static PrefabPath_BlockRemoveParticle = 'ab_lobby/Particle/BlockRemoveParticle/BlockRemoveParticle';

    static PrefabPath_IceAtt = 'ab_lobby/Particle/iceatt0/IceAtt';
    static PrefabPath_BlindAtt = 'ab_lobby/Particle/blindatt0/BlindAtt';
    static PrefabPath_KeyFly = 'ab_lobby/Particle/key0/KeyFly';
    static PrefabPath_StarBurst = 'ab_lobby/Particle/StarBurst0/StarBurst0';
    static PrefabPath_StarBurst1 = 'ab_lobby/Particle/StarBurst1/StarBurst1';
    static PrefabPath_IceBurst0 = 'ab_lobby/Particle/IceBurst0/IceBurst0';
    static PrefabPath_IceBurst1 = 'ab_lobby/Particle/IceBurst0/IceBurst1';
    // static PrefabPath_IceAtt_Wave = 'ab_lobby/Particle/iceatt0/wave';

    static PrefabPath_Ground = 'ab_lobby/Prefabs/Stage3d/Ground/Ground';
    static GroundPool = new SmartNodePool();
    static PrefabPath_Block = 'ab_lobby/Prefabs/Stage3d/Block/Block';
    static BlockPool = new SmartNodePool();

    static PrefabPath_BlockEdgeParticle = 'ab_lobby/Particle/blockEdge/BlockEdgeParticle';
    static BlockEdgeParticle = new SmartNodePool();

    static WallPool = new SmartNodePool();
    static ArrowPool = new SmartNodePool();
    static JointPool = new SmartNodePool();
    static KeyPool = new SmartNodePool();
    static BarrierPool = new SmartNodePool();
    static AxisLockPool = new SmartNodePool();

    static SplitLongBlockPool = new SmartNodePool();
    static PreShineTip = new SmartNodePool();

    static ChangeSmokePool = new SmartNodePool();
    static SwimringPool = new SmartNodePool();
    // static FlyItemPool = new SmartNodePool();
    static FlyCoinPool = new SmartNodePool();
    static TutorialHandPool = new SmartNodePool();
    // static BlinkPlateDestroyPool = new SmartNodePool();
    static Burst0Pool = new SmartNodePool();
    static Burst1Pool = new SmartNodePool();
    static Burst2Pool = new SmartNodePool();
    static Burst3Pool = new SmartNodePool();
    static Burst4Pool = new SmartNodePool();
    static BlockRemoveParticlePool = new SmartNodePool();

    static IceAttPool = new SmartNodePool();
    static BlindAttPool = new SmartNodePool();
    static IceBurst0Pool = new SmartNodePool();
    static IceBurst1Pool = new SmartNodePool();
    // static IceAttWavePool = new SmartNodePool();
    static KeyFlyPool = new SmartNodePool();
    static StarBurstPool = new SmartNodePool();
    static StarBurst1Pool = new SmartNodePool();

    static PreparePool() {

        this.GroundPool.setPrefab(rm.prefabs[this.PrefabPath_Ground]);
        this.GroundPool.prepare(100);
        this.BlockPool.setPrefab(rm.prefabs[this.PrefabPath_Block]);
        this.BlockPool.prepare(2);

        this.BlockEdgeParticle.setPrefab(rm.prefabs[this.PrefabPath_BlockEdgeParticle]);
        this.BlockEdgeParticle.prepare(10);

        this.ChangeSmokePool.setPrefab(rm.prefabs[this.PrefabPath_ChangeSmoke]);
        this.ChangeSmokePool.prepare(2);
        // this.FlyItemPool.setPrefab(rm.prefabs[this.PrefabPath_FlyItem]);
        // this.FlyItemPool.prepare(10);
        this.FlyCoinPool.setPrefab(rm.prefabs[this.PrefabPath_FlyCoin]);
        this.FlyCoinPool.prepare(100);
        this.TutorialHandPool.setPrefab(rm.prefabs[this.PrefabPath_TutorialHand]);
        this.TutorialHandPool.prepare(1);
        // this.BlinkPlateDestroyPool.setPrefab(rm.prefabs[this.PrefabPath_BlinkPlateDestroy]);
        // this.BlinkPlateDestroyPool.prepare(6);
        this.Burst0Pool.setPrefab(rm.prefabs[this.PrefabPath_BurstView]);
        this.Burst0Pool.prepare(6);
        this.Burst1Pool.setPrefab(rm.prefabs[this.PrefabPath_Burst1View]);
        this.Burst1Pool.prepare(6);
        this.Burst2Pool.setPrefab(rm.prefabs[this.PrefabPath_Burst2View]);
        this.Burst2Pool.prepare(1);
        this.Burst3Pool.setPrefab(rm.prefabs[this.PrefabPath_Burst3View]);
        this.Burst3Pool.prepare(2);
        this.Burst4Pool.setPrefab(rm.prefabs[this.PrefabPath_Burst4View]);
        this.Burst4Pool.prepare(6);

        this.BlockRemoveParticlePool.setPrefab(rm.prefabs[this.PrefabPath_BlockRemoveParticle]);
        this.BlockRemoveParticlePool.prepare(12);

        this.IceAttPool.setPrefab(rm.prefabs[this.PrefabPath_IceAtt]);
        this.IceAttPool.prepare(10);
        this.BlindAttPool.setPrefab(rm.prefabs[this.PrefabPath_BlindAtt]);
        this.BlindAttPool.prepare(10);
        this.IceBurst0Pool.setPrefab(rm.prefabs[this.PrefabPath_IceBurst0]);
        this.IceBurst0Pool.prepare(12);
        this.IceBurst1Pool.setPrefab(rm.prefabs[this.PrefabPath_IceBurst1]);
        this.IceBurst1Pool.prepare(12);

        // this.IceAttWavePool.setPrefab(rm.prefabs[this.PrefabPath_IceAtt_Wave]);
        // this.IceAttWavePool.prepare(12);
        this.KeyFlyPool.setPrefab(rm.prefabs[this.PrefabPath_KeyFly]);
        this.KeyFlyPool.prepare(6);
        this.StarBurstPool.setPrefab(rm.prefabs[this.PrefabPath_StarBurst]);
        this.StarBurstPool.prepare(6);
        this.StarBurst1Pool.setPrefab(rm.prefabs[this.PrefabPath_StarBurst1]);
        this.StarBurst1Pool.prepare(2);

        CaidaiHelper.PrepareCaidai();
    }

    static ResList = [

        [this.PrefabPath_Ground, ResType.Prefab, 0],
        [this.PrefabPath_Block, ResType.Prefab, 0],
        [this.PrefabPath_BlockEdgeParticle, ResType.Prefab, 0],

        [this.Atlas_Tptex2_Path, ResType.SpriteAtlas, 0],
        [this.Atlas_joint_Path, ResType.SpriteAtlas, 0],
        [CaidaiHelper.PrefabPath_Caidai_0, ResType.Prefab, 0],
        [CaidaiHelper.PrefabPath_Caidai_1, ResType.Prefab, 0],
        // [CaidaiHelper.PrefabPath_Caidai_2, ResType.Prefab, 0],
        [this.PrefabPath_ChangeSmoke, ResType.Prefab, 0],
        [this.PrefabPath_FlyCoin, ResType.Prefab, 0],
        [this.PrefabPath_TutorialHand, ResType.Prefab, 0],
        [this.PrefabPath_BlinkPlateDestroy, ResType.Prefab, 0],
        [this.PrefabPath_BurstView, ResType.Prefab, 0],
        [this.PrefabPath_Burst1View, ResType.Prefab, 0],
        [this.PrefabPath_Burst2View, ResType.Prefab, 60],
        [this.PrefabPath_Burst3View, ResType.Prefab, 60],
        [this.PrefabPath_Burst4View, ResType.Prefab, 140],
        [this.PrefabPath_BlockRemoveParticle, ResType.Prefab, 0],
        [this.PrefabPath_IceAtt, ResType.Prefab, 25],
        [this.PrefabPath_BlindAtt, ResType.Prefab, 25],
        [this.PrefabPath_KeyFly, ResType.Prefab, 60],
        [this.PrefabPath_StarBurst, ResType.Prefab, 0],
        [this.PrefabPath_StarBurst1, ResType.Prefab, 0],
        [this.PrefabPath_IceBurst0, ResType.Prefab, 25],
        [this.PrefabPath_IceBurst1, ResType.Prefab, 115],
        // ...Array.from({ length: 9 }, (v, k) => [this.GetAtlasB0CXPath(k + 1), ResType.SpriteAtlas]),
    ];

    static EditResList = [
    ];

}

globalThis.ResourceHelper = ResourceHelper;